`include "./src/Utils/im.v"
`include "./src/Utils/pc.v"
`include "./src/Utils/alu.v" 
`include "./src/Controller/alu_ctr.v"
`include "./src/Controller/mux.v"
`include "./src/Utils/dm.v"
`include "./src/Utils/ext.v"
`include "./src/Utils/reg.v"
`include "./src/Utils/pc_adder.v"
`include "./src/Utils/npc.v"
`include "./src/Pipe/reg_if_id.v"
`include "./src/Pipe/reg_id_ex.v"
`include "./src/Pipe/reg_ex_mem.v"
`include "./src/Pipe/reg_mem_wb.v"
`include "./src/Hazard/forword.v"
`include "./src/Hazard/hazard.v"
module Datapath(
    input  [1:0]  RegDes,      
    input  [1:0]  Branch,      
    input  [1:0]  MemtoReg, 
    input  [3:0]  AluOp, 
    input         MemWrite,   
    input         AluSrc,      
    input         RegWrite,    
    input  [1:0]  Jump,        
    input         Sign,
    input  [1:0]  DataType,
    input         DataSign,
    input         MemRead,
    input  clk,         
    input  rst,     
    output [31:0] instr

);
    wire  hazard_detector_stall_out; 
    wire         npc_PcSrc_out;
    wire [31:0]  reg_if_id_pc_out;
    wire [31:0]  reg_if_id_instr_out;

    wire [31:0] reg_rs_out;
    wire [31:0] reg_rt_out;
    wire [1:0]forword_branch_HazardA_out;
    wire [1:0]forword_branch_HazardB_out;
    wire   [1:0]    reg_id_ex_Branch_out;      
    wire   [1:0]    reg_id_ex_MemtoReg_out;   
    wire            reg_id_ex_AluSrc_out;      
    wire   [3:0]    reg_id_ex_AluOp_out;  
    wire            reg_id_ex_MemWrite_out;    
    wire            reg_id_ex_RegWrite_out;    
    wire   [1:0]    reg_id_ex_Jump_out;        
    wire            reg_id_ex_Sign_out;
    wire   [31:0]   reg_id_ex_pc_out;
    wire   [31:0]   reg_id_ex_data_rs_out;
    wire   [31:0]   reg_id_ex_data_rt_out;
    wire   [15:0]   reg_id_ex_immediate_out;
    wire   [4:0]    reg_id_ex_des_reg_out;
    wire   [31:0]   reg_id_ex_instr_out;
    wire   [1:0]    reg_id_ex_DataType_out;
    wire            reg_id_ex_DataSign_out;
    wire            reg_id_ex_mem_read_out;

    wire [31:0] npc_next_pc_out;
    wire [31:0] extender_immediate_out;

    wire [1:0]      reg_ex_mem_Branch_out;
    wire [1:0]      reg_ex_mem_MemtoReg_out;
    wire            reg_ex_mem_MemWrite_out;
    wire [1:0]      reg_ex_mem_Jump_out;
    wire [31:0]     reg_ex_mem_pc_out;
    wire [31:0]     reg_ex_mem_next_pc_out;
    wire            reg_ex_mem_zero_out;
    wire [31:0]     reg_ex_mem_result_out;
    wire [31:0]     reg_ex_mem_data_rt_out;
    wire [4:0]      reg_ex_mem_des_reg_out;
    wire [1:0]      reg_ex_mem_DataType_out;
    wire            reg_ex_mem_DataSign_out;
    wire            reg_ex_mem_MemRead_out;

    wire   [31:0]  im_instr_out;           
    wire   [31:0]  writedata;  
    wire   [31:0]  data_rs, data_rt;        
    wire   [31:0]  result;     
        
    wire [31:0]   mux_pc_out;
    wire[31:0]    pc_out;
    wire [31:0]   pc_adder_out;

    wire   [ 3:0]  AluCtrl; 

    wire [31:0] mux_alu_out;
    wire alu_ctrl_alu_src_a_out;


    wire alu_zero_out;
    wire [31:0] alu_result_out;

    wire [1:0] forword_alu_HazardRs_out;
    wire [1:0] forword_alu_HazardRt_out;
    wire            reg_ex_mem_RegWrite_out;

    wire [31:0] mux_rt_out_data;
    wire [4:0]  mux_reg_des_reg;
    wire [31:0] mux_hazard_rs_data_out;
    wire [31:0] mux_hazard_rt_data_out;
    assign instr = reg_if_id_instr_out;
    wire [31:0] mux_branch_a_out;
    wire [31:0] mux_branch_b_out;
    wire [31:0] dm_data_out;


    wire [31:0] mux_reg_data_write_data_out;

    wire [1:0]  reg_mem_wb_MemtoReg_out;
    wire        reg_mem_wb_RegWrite_out;
    wire [31:0] reg_mem_wb_dm_data_out;
    wire [31:0] reg_mem_wb_alu_result_out;
    wire [4:0]  reg_mem_wb_dm_des_reg_out;
    wire [31:0] reg_mem_wb_pc_out;
    wire [1:0] 	rs_hazard;
    wire [1:0] 	rt_hazard;

    wire [31:0]  mux_rt_data_out;

    MuxPc mux_pc(npc_PcSrc_out,pc_adder_out,npc_next_pc_out,mux_pc_out);
    Pc pc(mux_pc_out, clk, rst, hazard_detector_stall_out, pc_out);
    PcAdder pc_adder(pc_out,pc_adder_out);
    
    

    im_4k im(pc_out[11:0],im_instr_out);

   
    
    RegIfId reg_if_id(pc_adder_out,im_instr_out,npc_PcSrc_out, hazard_detector_stall_out,clk,reg_if_id_pc_out,reg_if_id_instr_out);
    
   HazardDetectorBranch hazard_detector_branch(reg_if_id_instr_out[25:21], reg_if_id_instr_out[20:16],Branch,reg_id_ex_mem_read_out,reg_id_ex_des_reg_out,reg_ex_mem_MemRead_out,reg_ex_mem_des_reg_out,rst,hazard_detector_stall_out);


    Reg regfile(reg_if_id_instr_out[25:21], reg_if_id_instr_out[20:16], reg_mem_wb_dm_des_reg_out, reg_mem_wb_RegWrite_out,mux_reg_data_write_data_out, clk,rst,reg_rs_out,reg_rt_out);
    
    MuxReg mux_reg(reg_if_id_instr_out[20:16], reg_if_id_instr_out[15:11], RegDes, mux_reg_des_reg);
    ForwordBranch forword_branch(Branch,reg_if_id_instr_out[25:21],reg_if_id_instr_out[20:16],reg_ex_mem_des_reg_out,reg_ex_mem_RegWrite_out,reg_mem_wb_dm_des_reg_out,reg_mem_wb_RegWrite_out,forword_branch_HazardA_out,forword_branch_HazardB_out);
    MuxBranchA mux_branch_a(forword_branch_HazardA_out,reg_rs_out,reg_ex_mem_result_out,mux_reg_data_write_data_out,mux_branch_a_out);
    MuxBranchB mux_branch_b(forword_branch_HazardB_out,reg_rt_out,reg_ex_mem_result_out,mux_reg_data_write_data_out,mux_branch_b_out);
    Npc npc(reg_if_id_pc_out,mux_branch_a_out,mux_branch_b_out,Jump,Branch, reg_if_id_instr_out,npc_PcSrc_out,npc_next_pc_out);

   RegIdEx reg_id_ex(Branch,MemtoReg,AluOp,MemWrite,AluSrc,RegWrite,Jump,Sign,DataType,DataSign,MemRead,reg_if_id_pc_out,
    reg_rs_out,reg_rt_out,reg_if_id_instr_out[15:0],mux_reg_des_reg,reg_if_id_instr_out, hazard_detector_stall_out,clk,   
    reg_id_ex_Branch_out,     
    reg_id_ex_MemtoReg_out,   
    reg_id_ex_AluOp_out, 
    reg_id_ex_MemWrite_out,  
    reg_id_ex_AluSrc_out,
    reg_id_ex_RegWrite_out,   
    reg_id_ex_Jump_out,       
    reg_id_ex_Sign_out,
    reg_id_ex_pc_out,
    reg_id_ex_data_rs_out,
    reg_id_ex_data_rt_out,
    reg_id_ex_immediate_out,
    reg_id_ex_des_reg_out,
    reg_id_ex_instr_out,
    reg_id_ex_DataType_out,
    reg_id_ex_DataSign_out,
    reg_id_ex_mem_read_out
    );

  

    
    Extender extender(reg_id_ex_immediate_out,reg_id_ex_Sign_out,extender_immediate_out);

    MuxHazardRs mux_rs(forword_alu_HazardRs_out,reg_id_ex_data_rs_out,reg_ex_mem_result_out,mux_reg_data_write_data_out,mux_hazard_rs_data_out);
    MuxHazardRt mux_hazard_rt(reg_id_ex_data_rt_out,forword_alu_HazardRt_out,reg_ex_mem_result_out,mux_reg_data_write_data_out,mux_hazard_rt_data_out);

    MuxRt mux_rt(mux_hazard_rt_data_out,extender_immediate_out,reg_id_ex_AluSrc_out,mux_rt_data_out);
   

    
    AluControl alu_ctr(reg_id_ex_AluOp_out,reg_id_ex_immediate_out[5:0],AluCtrl);

    
    ForwordAlu forword_alu(reg_id_ex_instr_out[25:21], reg_id_ex_instr_out[20:16],reg_ex_mem_des_reg_out,reg_ex_mem_RegWrite_out,reg_mem_wb_dm_des_reg_out,reg_mem_wb_RegWrite_out,forword_alu_HazardRs_out,forword_alu_HazardRt_out);
    
    Alu alu( AluCtrl,mux_hazard_rs_data_out ,mux_rt_data_out,reg_id_ex_immediate_out[10:6],alu_zero_out, alu_result_out);


    
    

    RegExMem reg_ex_mem( reg_id_ex_Branch_out,reg_id_ex_MemtoReg_out, reg_id_ex_MemWrite_out,reg_id_ex_RegWrite_out,reg_id_ex_Jump_out,reg_id_ex_DataType_out,reg_id_ex_DataSign_out,reg_id_ex_pc_out,npc_next_pc_out,  alu_result_out, alu_zero_out,mux_hazard_rt_data_out, reg_id_ex_des_reg_out,reg_id_ex_mem_read_out, clk,reg_ex_mem_Branch_out,reg_ex_mem_MemtoReg_out,reg_ex_mem_MemWrite_out,reg_ex_mem_RegWrite_out,reg_ex_mem_Jump_out,reg_ex_mem_DataType_out,reg_ex_mem_DataSign_out,reg_ex_mem_pc_out,reg_ex_mem_next_pc_out,reg_ex_mem_zero_out,reg_ex_mem_result_out,reg_ex_mem_data_rt_out,reg_ex_mem_des_reg_out,reg_ex_mem_MemRead_out);




    dm_4k dm(reg_ex_mem_result_out[11:0], reg_ex_mem_data_rt_out, reg_ex_mem_MemWrite_out,reg_ex_mem_DataType_out,reg_ex_mem_DataSign_out, clk, dm_data_out);

   
    RegMemWb reg_mem_wb(reg_ex_mem_MemtoReg_out,reg_ex_mem_RegWrite_out,dm_data_out,reg_ex_mem_result_out,reg_ex_mem_des_reg_out,reg_ex_mem_pc_out,clk,reg_mem_wb_MemtoReg_out,reg_mem_wb_RegWrite_out,reg_mem_wb_dm_data_out,reg_mem_wb_alu_result_out,reg_mem_wb_dm_des_reg_out,reg_mem_wb_pc_out);

  
    MuxRegData mux_reg_data(reg_mem_wb_dm_data_out,reg_mem_wb_alu_result_out,reg_mem_wb_pc_out,reg_mem_wb_MemtoReg_out,mux_reg_data_write_data_out);
    



endmodule